/* eslint-disable react/no-danger */
/**
 * 发起申请、流程模板 --流程表单。
 */
import React, { useEffect, useState } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'umi';
import { Button, Card, Form, Skeleton, Row, Col, Spin, Select } from 'antd';
import useDeepCompareEffect from 'use-deep-compare-effect';
import xss from 'xss';
import moment from 'moment';
import cn from 'classnames';

import { BottomAction } from '@/components';
import JsonForm from '@/components/JsonForm';
import Step from '@/components/Step';
import PageHeaderWrapper from '@/components/PageHeaderWrapper';
import PageRouter from '@/components/PageRouter/PageRouter';
import { modifyProps, modifyItemProps } from '@/pages/Flow/Mine/Apply/utils';
import { getOptionData } from '@/pages/Flow/Mine/ApplyPage/utils';
import { useGradeType, useGrade } from '@/pages/JobRank/hooks';
import request from '@/utils/request';
import { withRoutePage } from '@/utils/enhanceUtils';
import { dictionaryList } from '@/services/dictionary';
import { companysearchCandidate as searchCandidate } from '@/services/flowMine/apply';
import { history } from 'umi'
import pageTabUtil from '@/utils/pageTabUtil';
import { fetchVersionDetaillist } from '@/services/setting/salaryReference';
import { handleSubmit, submitApply, getJsonStr, onNewsPreview } from './utils';
import { useFormDetail, useFormJson, useProcess } from './hooks';
import dealFieldChange from './dealFieldChange';
import didMount from './didMount';
import useFinalJSON from './useFinalJSON';
import fillForm from './fillForm';
import FORM_TYPE_MAP from './consts';
import styles from './ApplyPage.less';
// 注意：销假流程不走 JSON 渲染模式
import { ResumeLeave } from '../../Factory';

const { Option } = Select;

const COUNTRY_TYPE_MAP = {
    xiamen: 'China',
    shenzhen: 'China',
    singapore: 'Singapore'
};
const generateFormLayout = formType => {
    if (formType === FORM_TYPE_MAP.TYPE_ON_RECRUIT) {
        return {
            labelCol: {
                span: 6
            },
            wrapperCol: {
                span: 18
            }
        };
    }
    if (formType === FORM_TYPE_MAP.TYPE_ON_OFFER) {
        return {
            labelCol: {
                span: 8
            },
            wrapperCol: {
                span: 16
            }
        };
    }
    if (formType === FORM_TYPE_MAP.TYPE_ON_NEWS) {
        return {
            labelCol: {
                span: 10
            },
            wrapperCol: {
                span: 14
            }
        };
    }
    return {
        labelCol: { span: 4 },
        wrapperCol: { span: 12 }
    };
};

const ApplyPage = props => {
    const { form, dispatch, location, templateId: templateIdProps, disabledForm, onlyShowForm, onlyShowFields } = props;

    const { query = {} } = location;

    const {
        id,
        applicationNo,
        formDeploymentId,
        processDeploymentId,
        templateId,
        templateName,
        reedit,
        ...restQuery
    } = query;

    const currentUser = localStorage.getItem('user') ? JSON.parse(localStorage.getItem('user')) : {};

    const [pageLoading, setPageLoading] = useState(true); // 请求数据标识
    const [loading, setLoading] = useState(false);
    const [saveLoading, setSaveLoading] = useState(false);

    const [isDataReady, setIsDataReady] = useState(false);

    const [postId, setPostId] = useState();
    const [postType, setPostType] = useState([]); // 职级类型
    const [levelType, setLevelType] = useState([]); // 职级水平
    const [reason1, setReason1] = useState([]);
    const [reason2, setReason2] = useState([]);
    const [takeUsers, setTakeUsers] = useState([]); // 录取人
    const [curPost, setCurPost] = useState(''); // 当前选中的录用人
    const [postList, setPostList] = useState(''); // 需求岗位
    const [leaders, setLeaders] = useState([]); // 试用期带教人
    const [recoder, setRecorder] = useState([]); // 背调记录人
    const [fetching, setFetching] = useState(false); // 模糊搜索加载中
    const [attachmentRequired, setAttachmentRequired] = useState(false); // 请假表单-附件是否必填
    const [institutionType, setInstitutionType] = useState([]); // 制度发布表单-制度类型
    const [originInstitutionName, setOriginInstitutionName] = useState([]); // 制度发布表单-发布类型中已有制度修改类型下的下拉

    // 获取动态表单 JSON 配置
    const [templateLoading, json, setJson] = useFormJson({
        templateId: templateIdProps || templateId,
        applicationNo,
        formDeploymentId,
        form,
        onlyShowForm,
        restQuery,
        currentUser,
        postId,
        setTakeUsers,
        setPostList,
        setLeaders,
        setRecorder,
        fetching,
        setFetching,
        institutionType,
        setOriginInstitutionName
    });

    const { key, fields } = json;
    const [valueJson, detailLoading] = useFormDetail(applicationNo); // 表单的值
    const [duration, setDuration] = useState(valueJson.formValueJson.duration || 0); // 时长
    const [leaveTypeList, setLeaveTypeList] = useState([]); // 请假类型单位
    const overtimeList = [];
    const [keyPrefix = '', FORM_TYPE = ''] = key.split('-'); // 表单唯一 Key 值
    const COUNTRY = COUNTRY_TYPE_MAP[keyPrefix] === 'China' ? 'zh' : 'sg'; // 国家，目前只支持 zh 和 sg

    // 是否显示两列
    const inlineTypes = [FORM_TYPE_MAP.TYPE_ON_RECRUIT, FORM_TYPE_MAP.TYPE_ON_OFFER, FORM_TYPE_MAP.TYPE_ON_NEWS];
    const inline = inlineTypes.includes(FORM_TYPE);
    const customLayout = generateFormLayout(FORM_TYPE);

    // 审批流程详情
    const [process] = useProcess(
        JSON.stringify(getJsonStr(fields, form, duration, FORM_TYPE, currentUser, true)),
        processDeploymentId,
        applicationNo,
        FORM_TYPE
    );

    // 保存流程
    const handleSave = () => {
        handleSubmit(
            fields,
            form,
            applicationNo,
            duration,
            FORM_TYPE,
            setSaveLoading,
            {
                formDeploymentId,
                id,
                processDeploymentId,
                templateId,
                templateName
            },
            currentUser,
            location.query,
            valueJson,
            postList
        );
    };

    // 提交申请
    const handleSubmitApply = e => {
        submitApply(
            e,
            fields,
            form,
            duration,
            FORM_TYPE,
            setLoading,
            {
                formDeploymentId,
                id,
                processDeploymentId,
                templateId,
                templateName
            },
            currentUser,
            location.query,
            valueJson,
            postList
        );
    };

    // 预览新闻
    const onPreview = e => {
        e.preventDefault();
        onNewsPreview({ form });
    };

    // 动态更改标签显示名称
    useEffect(() => {
        const setTabName = async () => {
            let tabName = json.name;

            // 临时的判断薪资参考的表单数据，然后修改标签名称
            if (json.name === '薪酬标准发布申请') {
                setFetching(true);
                const { data = {}, code } = await fetchVersionDetaillist({
                    salaryStandardVersion: query.version,
                    changeType: 0,
                    pageNo: 1,
                    pageSize: 1
                });
                if (code === 10000) {
                    const standardName = data?.rows?.[0]?.salaryStandardName ?? '';
                    tabName = (standardName.includes('微微') ? '微微' : '市场') + tabName;
                }
                setFetching(false);
            }

            if (tabName) {
                dispatch({
                    type: 'menu/changeMenuName',
                    payload: {
                        path: location.pathname,
                        newName: tabName
                    }
                });
            }
        };
        setTabName();
        return () => {
            dispatch({
                type: 'menu/changeMenuName',
                payload: {
                    path: location.pathname,
                    newName: '发起申请'
                }
            });
        };
    }, [json.name]);

    // ----------------------------------------------------------------- offer 相关逻辑开始
    useEffect(() => {
        if (restQuery.talentName && restQuery.talentId && postType.length > 0) {
            searchCandidate({
                candidateName: restQuery.talentName,
                companyId: currentUser.companyId,
                searchStage: 'offer'
            }).then(async response => {
                if (response.code === 10000 && response.data.length > 0) {
                    const find = response.data.find(user => user.candidateCode === restQuery.talentId);
                    setTakeUsers(response.data);

                    if (find) {
                        form.setFieldsValue({
                            talentSex: find.talentSex || '',
                            talentBirth: {
                                ...form.getFieldValue('talentBirth'),
                                time: find.talentBirth ? moment(find.talentBirth) : null
                            },
                            talentAgree: find.talentDegree || '',
                            entryPost: (find.recruitPostId && String(find.recruitPostId)) || '',
                            postType: find.postType || '',
                            demandDepartmentId: find.departmentIds || [],
                            entryLevel: find.postGradeCode || '',
                            talentName: restQuery.talentId
                        });

                        if (find.postType) {
                            const cur = postType.find(level => level.dictValue === find.postType);
                            if (cur && cur.remark) {
                                setFetching(true);
                                const result = await dictionaryList({
                                    code: cur.remark
                                });
                                setFetching(false);
                                if (result.code === 10000) {
                                    setLevelType(result.data);
                                }
                            }
                        }
                        setPostId(find.recruitPostId);
                        setCurPost(find.recruitPost);
                    }
                }
                setPageLoading(false);
            });
        }
    }, [restQuery.talentName, restQuery.talentId, postType]);

    useEffect(() => {
        const fetchTeacher = async () => {
            if (currentUser.id && FORM_TYPE === FORM_TYPE_MAP.TYPE_ON_OFFER) {
                if (!valueJson.backRecorderId) {
                    const response = await request('/api/oa/v1/employee/getservicepersonlist', {
                        method: 'POST',
                        data: {
                            companyId: currentUser.companyId,
                            userName: currentUser.employeeName
                        }
                    });
                    if (response.code === 10000) {
                        setRecorder(response.data);
                        form.setFieldsValue({
                            backRecorderId: currentUser.id
                        });
                    }
                }
            }
        };
        fetchTeacher();
    }, [FORM_TYPE, valueJson.backRecorderId]);
    // ----------------------------------------------------------------- offer 相关逻辑结束

    // 注意：用于处理一些需要加载来获取数据的表单项，比如：请假类型
    useEffect(() => {
        if (!FORM_TYPE) {
            return;
        }
        didMount({
            formType: FORM_TYPE,
            json,
            setJson,
            setPostId,
            setLeaveTypeList, // 用于设置请假类型
            curPost, // 当前选中的录用人
            setPostType,
            setReason1,
            currentUser,
            setPageLoading: applicationNo ? () => {} : setPageLoading,
            country: keyPrefix,
            setInstitutionType,
            setPostList,
            valueJson,
            applicationNo,
            setIsDataReady
        });
    }, [FORM_TYPE, curPost, valueJson]);

    // 注意：用于回填表单值
    useDeepCompareEffect(() => {
        const fill = () => {
            fillForm({
                query,
                form,
                currentUser,
                country: COUNTRY,
                formType: FORM_TYPE,
                valueJson,
                leaveTypeList,
                postType,
                reason1,
                setDuration,
                setLevelType,
                setReason2,
                setTakeUsers,
                setPostList,
                setLeaders,
                setRecorder,
                setPageLoading,
                setFetching,
                setOriginInstitutionName
            });
        };
        // 回填表单值
        if (applicationNo && Object.keys(valueJson.formValueJson).length !== 0) {
            if (FORM_TYPE === FORM_TYPE_MAP.TYPE_ON_RECRUIT) {
                if (postType.length > 0 && reason1.length > 0) {
                    fill();
                }
            } else if (FORM_TYPE === FORM_TYPE_MAP.TYPE_ON_OFFER) {
                if (postType.length > 0) {
                    fill();
                }
            } else if (FORM_TYPE === FORM_TYPE_MAP.TYPE_ON_SYSTEM) {
                if (institutionType.length > 0) {
                    fill();
                }
            } else {
                fill();
            }
        }
    }, [leaveTypeList, valueJson.formValueJson, postType, reason1, institutionType]);
    const recruitPostHelp = () => {
        if (postList !== '' && postList.length === 0) {
            const link = () => {
                const path = '/office/personnelManagement/organization/employeeList';
                pageTabUtil.openTab(path);
                history.push(path);
            };
            return (
                <div style={{ fontSize: 12 }}>
                    未找到需求职位,请前往
                    <a
                        onClick={() => {
                            link();
                        }}
                    >
                        组织管理
                    </a>
                    设置
                </div>
            );
        }
        return '';
    };
    // 动态 options
    useEffect(() => {
        let tmpJson = { ...json };
        tmpJson = {
            ...tmpJson,
            fields: modifyProps(
                'postLevel',
                {
                    options: getOptionData(levelType || [], {
                        key: 'dictValue',
                        label: 'dictName'
                    })
                },
                tmpJson.fields
            )
        };
        tmpJson = {
            ...tmpJson,
            fields: modifyProps(
                'entryLevel',
                {
                    options: getOptionData(levelType || [], {
                        key: 'dictValue',
                        label: 'dictName'
                    })
                },
                tmpJson.fields
            )
        };
        tmpJson = {
            ...tmpJson,
            fields: modifyProps(
                'reason2',
                {
                    options: getOptionData(reason2 || [], {
                        key: 'dictValue',
                        label: 'dictName'
                    })
                },
                tmpJson.fields
            )
        };
        tmpJson = {
            ...tmpJson,
            fields: modifyProps(
                'talentName',
                {
                    optionLabelProp: 'label',
                    options: getOptionData(
                        takeUsers || [],
                        {
                            key: 'candidateCode',
                            label: 'talentName'
                        },
                        true
                    ),
                    customRender: (_, item) => (
                        <Option key={item.key} value={item.key} label={item.label}>
                            {item.label}
                            <span style={{ color: '#999' }}>（{item.recruitPost || ''}）</span>
                        </Option>
                    )
                },
                tmpJson.fields
            )
        };
        // 招聘需求岗位
        tmpJson = {
            ...tmpJson,
            fields: modifyProps(
                'recruitPost',
                {
                    optionLabelProp: 'label',
                    options: getOptionData(
                        postList || [],
                        {
                            key: 'id',
                            label: 'postName'
                        },
                        true
                    )
                },
                tmpJson.fields
            )
        };
        // offer申请岗位
        tmpJson = {
            ...tmpJson,
            fields: modifyProps(
                'entryPost',
                {
                    optionLabelProp: 'label',
                    options: getOptionData(
                        postList || [],
                        {
                            key: 'id',
                            label: 'postName'
                        },
                        true
                    ),
                    customRender: (_, item) => (
                        <Option key={item.key} value={item.key} label={item.label}>
                            {item.label}
                        </Option>
                    )
                },
                tmpJson.fields
            )
        };
        // offer薪资参考
        tmpJson = {
            ...tmpJson,
            fields: modifyProps(
                'salaryRef',
                {
                    postId
                },
                tmpJson.fields
            )
        };
        tmpJson = {
            ...tmpJson,
            fields: modifyProps(
                'teacherId',
                {
                    options: getOptionData(leaders || [], {
                        key: 'id',
                        label: 'employeeName'
                    })
                },
                tmpJson.fields
            )
        };
        tmpJson = {
            ...tmpJson,
            fields: modifyProps(
                'backRecorderId',
                {
                    options: getOptionData(recoder || [], {
                        key: 'id',
                        label: 'employeeName'
                    })
                },
                tmpJson.fields
            )
        };
        tmpJson = {
            ...tmpJson,
            fields: modifyProps(
                'originInstitutionId',
                {
                    options: getOptionData(originInstitutionName || [], {
                        key: 'id',
                        label: 'institutionName'
                    })
                },
                tmpJson.fields
            )
        };
        tmpJson = {
            ...tmpJson,
            fields: modifyItemProps(
                'recruitPost',
                {
                    help: recruitPostHelp()
                },
                tmpJson.fields
            )
        };

        setJson(tmpJson);
    }, [
        JSON.stringify(json),
        JSON.stringify(levelType),
        JSON.stringify(reason2),
        JSON.stringify(takeUsers),
        JSON.stringify(postList),
        JSON.stringify(postId),
        JSON.stringify(leaders),
        JSON.stringify(recoder),
        JSON.stringify(originInstitutionName)
    ]);

    useEffect(() => {
        form.validateFields(['attachment'], { force: true });
    }, [attachmentRequired]);

    // ----------------------------------------------------------------- 职级相关逻辑开始
    const PROPS = React.useMemo(
        () => ({ templateLoading, type: FORM_TYPE, json, setJson, query, setPageLoading, currentUser }),
        [FORM_TYPE, json, setJson, query, setPageLoading, currentUser, templateLoading]
    );
    // 用于职级相关流程最后处理表单 json 渲染数据
    useFinalJSON(PROPS);

    const commonGradeKeys = [
        'companyCode',
        'institutionIntroduce',
        'institutionName',
        'institutionNo',
        'institutionType'
    ];
    const [, gradeTypeDetail] = useGradeType(query.GRADE_TYPE_ID);
    React.useEffect(() => {
        if (gradeTypeDetail && !applicationNo && !templateLoading) {
            const final = { ...gradeTypeDetail };
            const finalKeys = [...commonGradeKeys, 'rankTypeDesc', 'rankTypeName']; // , 'modifyRemark']; // 编辑时不能带上原来的原因
            finalKeys.forEach(fieldName => {
                form.setFieldsValue({
                    [fieldName]: final[fieldName]
                });
            });
            form.setFieldsValue({
                originRankTypeName: final.rankTypeName,
                originRankTypeDesc: final.rankTypeDesc,
                originModifyRemark: final.modifyRemark,
                startTime: { time: moment(final.startTime) }
            });
        }
    }, [gradeTypeDetail, templateLoading]);

    // 初始化职级流程表单
    const [, gradeDetail] = useGrade(query.GRADE_ID);
    React.useEffect(() => {
        if (gradeDetail && !applicationNo && !templateLoading) {
            const final = { ...gradeDetail };
            const finalKeys = [
                ...commonGradeKeys,
                'rankDesc',
                'rankName',
                'rankValue',
                'rankTypeCode',
                'rankDimensions'
            ];
            finalKeys.forEach(fieldName => {
                form.setFieldsValue({
                    [fieldName]: final[fieldName]
                });
            });
            form.setFieldsValue({
                originRankName: final.rankName,
                originRankDesc: final.rankDesc,
                originRankValue: final.rankValue,
                originModifyRemark: final.modifyRemark,
                startTime: { time: moment(final.startTime) },
                originRankDimensions: final.rankDimensions || []
            });
        }
    }, [gradeDetail, templateLoading]);
    // ----------------------------------------------------------------- 职级相关逻辑结束

    // 渲染：流程说明
    const renderDescription = () => {
        let { description } = json;
        const { formValueJson = {} } = valueJson;

        if (onlyShowFields || !description) {
            return null;
        }

        // 注意：薪资回退这里需要兼容两个流程
        if (query.ftype === 'rollback' || formValueJson.ftype === 'rollback') {
            description = '恢复到历史版本，以下为该版本的完整内容';
        }
        return (
            <Form.Item
                wrapperCol={{
                    span: 24
                }}
            >
                <div className={styles.info}>
                    <b>流程说明</b>
                    <div className={styles.scroll} dangerouslySetInnerHTML={{ __html: xss(description) }} />
                </div>
            </Form.Item>
        );
    };

    // 渲染：表单主体内容
    const renderForm = () => (
        <Row className={styles.mainContent}>
            <Col xl={20}>
                <JsonForm
                    data={json}
                    form={form}
                    layout={customLayout}
                    inline={inline}
                    disabled={disabledForm}
                    fetching={fetching}
                    onChange={(item, value) =>
                        dealFieldChange({
                            id: item.id,
                            value,
                            form,
                            json,
                            setJson,
                            country: COUNTRY,
                            formType: FORM_TYPE,
                            currentUser,
                            leaveTypeList,
                            overtimeList,
                            postType,
                            takeUsers,
                            postList,
                            recoder,
                            reason1,
                            institutionType,
                            setPostId,
                            setReason2,
                            setDuration,
                            setLevelType,
                            setAttachmentRequired,
                            setOriginInstitutionName,
                            setCurPost,
                            setIsDataReady
                        })
                    }
                />
            </Col>
        </Row>
    );

    const handleCancel = () => {
        pageTabUtil.goBack();
    };

    const saveAvailable = isDataReady && !templateLoading && !pageLoading && !detailLoading;

    const renderButton = () => (
        <BottomAction>
            {FORM_TYPE === FORM_TYPE_MAP.TYPE_ON_NEWS && (
                <a href="#" onClick={onPreview}>
                    预览新闻
                </a>
            )}
            {(FORM_TYPE === FORM_TYPE_MAP.EDIT_SALARY || FORM_TYPE === FORM_TYPE_MAP.EDIT_POST_MAPPING) && (
                <Button onClick={handleCancel} loading={saveLoading}>
                    取消
                </Button>
            )}
            {FORM_TYPE !== FORM_TYPE_MAP.EDIT_SALARY && FORM_TYPE !== FORM_TYPE_MAP.EDIT_POST_MAPPING && !reedit && (
                <Button disabled={!saveAvailable} onClick={handleSave} loading={saveLoading}>
                    保存
                </Button>
            )}
            <Button
                htmlType="submit"
                disabled={!saveAvailable}
                type="primary"
                className="login-form-button"
                loading={loading}
            >
                提交
            </Button>
        </BottomAction>
    );

    // 渲染：审批流程
    const renderProcess = () => {
        if (onlyShowForm) {
            return null;
        }
        return (
            <>
                <h3 className={styles.title}>申请审批流程</h3>
                <Row style={{ marginLeft: 30 }}>
                    <Col offset={2}>
                        <Step data={process} />
                    </Col>
                </Row>
            </>
        );
    };

    const content = (
        <Card className={cn(styles[FORM_TYPE], styles.applyPage)} bordered={false}>
            <Skeleton active loading={fields.length === 0}>
                <Form {...customLayout} onSubmit={handleSubmitApply}>
                    <Spin spinning={pageLoading}>
                        {renderDescription()}
                        {renderForm()}
                        {renderProcess()}
                        {renderButton()}
                    </Spin>
                </Form>
            </Skeleton>
        </Card>
    );

    const special = <ResumeLeave shcema={json} detail={valueJson} progress={process} {...props} />;

    const finalContent = FORM_TYPE && FORM_TYPE === FORM_TYPE_MAP.TYPE_LEAVE_CANCEL ? special : content;

    return onlyShowForm ? (
        finalContent
    ) : (
        <PageHeaderWrapper type="success">
            <PageRouter type="myflow" activePath="/personal/portal/flow/mine/list">
                {finalContent}
            </PageRouter>
        </PageHeaderWrapper>
    );
};

ApplyPage.displayName = 'ApplyPageComponent';

ApplyPage.propTypes = {
    templateId: PropTypes.string,
    onlyShowForm: PropTypes.bool, // 仅显示表单
    onlyShowFields: PropTypes.bool, // 仅显示表单控件，不显示标题/流程说明
    location: PropTypes.object.isRequired
};

ApplyPage.defaultProps = {
    templateId: '',
    onlyShowForm: false, // 如果为 true，则只显示禁用状态下的表单
    onlyShowFields: false
};

export default withRoutePage(connect(({ user, loading, menu }) => ({ user, loading, menu }))(Form.create()(ApplyPage)));
